#pragma once

#include "land_graphics.h"

#include "land_2d_conf.h"

#define LAND_2D_OBJ_DIRTY_POSITION  (1)
#define LAND_2D_OBJ_DIRTY_ROTATION  (1 << 1)
#define LAND_2D_OBJ_DIRTY_SCALE     (1 << 2)
#define LAND_2D_OBJ_DIRTY_SIZE      (1 << 3)
#define LAND_2D_OBJ_DIRTY_COLOR     (1 << 4)
#define LAND_2D_OBJ_DIRTY_ANCHOR    (1 << 5)

enum {
    LAND_BUTTON_STATUS_UP,
    LAND_BUTTON_STATUS_HOVER,
    LAND_BUTTON_STATUS_DOWN,
};

enum {
    LAND_OBJ_WINDOW_EVENT,
    LAND_OBJ_CUSTOM_EVENT,
};

typedef struct  {
    LandRef ref;
    unsigned width;
    unsigned height;
    LandCanvas* canvas;
    LandDraw* draw;
    LandMatrix view;
}LandScene;

typedef struct {
    void (*beginDraw)(LandScene* scene);
    void (*readyDraw)(LandScene* scene);
}LandSceneMod;

typedef struct {
    int type;
    int intercept;
    void* ud;
}LandObjEvent;

typedef struct LandObj LandObj;
struct LandObj{
    LandRef ref;
    LandVector2D position;
    LandVector2D size;
    LandVector2D anchor;
    LandVector2D scale;
    LandFloat rotate;
    LandVector color;
    LandMatrix2D transform;
    LandVector rect;
    int dirty;
    int visible;
    LandObj** children;
    LandObj* childrenCache[8];
    unsigned count;
    unsigned cap;
    LandObj* parent;
    unsigned index;
    LandRefFree free;
    void (*visit)(LandObj* obj, LandMatrix2D* m, int force);
    void (*preDraw)(LandScene* scene, LandObj* obj);
    void (*draw)(LandScene* scene, LandObj* obj);
    void (*onEvent)(LandObj* obj, LandObjEvent* evt);
};

typedef struct{
    LandObj obj;
    LandList* list;
    unsigned offset;
    unsigned count;
} LandShape;

typedef struct {
    LandObj obj;
    LandTexture* texture;
    unsigned offset;
    unsigned count;
}LandImage;

typedef struct LandLabel LandLabel;
typedef struct {
    LandObj obj;
    LandFont* font;
    LandVertex* vertex;
    char* str;
    size_t len;
    int strDirty;
}LandText;

typedef struct LandSprite LandSprite;

typedef struct LandButton LandButton;
struct LandButton {
    LandObj obj;
    int status;
    void (*onStatus)(LandButton* btn, LandObjEvent* evt);
    void (*onClick)(LandButton* btn, LandObjEvent* evt);
};

LAND_2D_API int
landInit2D();

LAND_2D_API LandScene*
landNewScene(unsigned width, unsigned height);
LAND_2D_API void
landDrawScene(LandScene* scene, LandObj* obj);
LAND_2D_API void
landSceneSize(LandScene* scene, unsigned width, unsigned height);
LAND_2D_API void
landPushSceneMod(LandSceneMod* mod);

LAND_2D_API void*
landNewObj();
LAND_2D_API void*
landNewExtendObj(size_t size, LandRefFree free);
LAND_2D_API void
landAddObjChild(void* parent, void* child);
LAND_2D_API void
landRemoveObjChild(void* parent, void* child);
LAND_2D_API void
landObjPosition(void* obj, LandFloat x, LandFloat y);
LAND_2D_API void
landObjRotate(void* obj, LandFloat rotate);
LAND_2D_API void
landObjScale(void* obj, LandFloat x, LandFloat y);
LAND_2D_API void
landObjColor(void* obj, LandVector color);
LAND_2D_API void
landObjSize(void* obj, LandFloat x, LandFloat y);
LAND_2D_API void
landObjAnchor(void* obj, LandFloat x, LandFloat y);
LAND_2D_API void
landToObjWorld(void* obj, LandVector2D position, LandVector2D* res);
LAND_2D_API void
landToObjLocal(void* obj, LandVector2D position, LandVector2D* res);
LAND_2D_API void
landObjEvent(void* obj, LandObjEvent* evt);
LAND_2D_API int
landObjHit(void* obj, LandFloat x, LandFloat y);

LAND_2D_API LandShape*
landNewShape();
LAND_2D_API void
landClearShape(LandShape* shape);
LAND_2D_API void
landShapeRect(LandShape* shape, LandVector* rect, LandVector* color);

LAND_2D_API LandImage*
landNewImage(LandTexture* texture);

LAND_2D_API LandLabel*
landNewLabel(LandFont* font, unsigned fsize);
LAND_2D_API void
landLabelStr(LandLabel* label, const char* str, size_t len);
LAND_2D_API void
landLabelFontSize(LandLabel* label, unsigned fsize);

LAND_2D_API LandText*
landNewText(LandFont* font);
LAND_2D_API void
landTextStr(LandText* text, const char* str, size_t len);

LAND_2D_API LandSprite*
landNewSprite(LandFrame* frame);
LAND_2D_API void
landSpriteFrame(LandSprite* sprite, LandFrame* frame);
LAND_2D_API void
landSpriteIndex(LandSprite* sprite, unsigned index);

LAND_2D_API LandButton*
landNewButton();
LAND_2D_API LandButton*
landNewExtendButton(size_t size, LandRefFree free);
